package com.java.lock_problem;

/**
 * 死锁
 */
public class DeadLock {
    static final String LOCK_KEY1 = "LOCK_KEY1";
    static final String LOCK_KEY2 = "LOCK_KEY2";
    
    public static void main(String[] args) {
        // 互斥：synchronized同步代码块互斥
        // 请求与保持：获取第二个锁对象时发生阻塞，第一个锁对象不会释放
        // 不可剥夺：一旦获取到锁对象直到同步代码块内代码执行完才会释放
        // 循环等待：获取第二个锁对象是线程1等线程2，线程2等线程1
        new Thread(() -> {
            while (true) {
                try {
                    synchronized (LOCK_KEY1) {
                        System.out.println(Thread.currentThread().getName() + "获取LOCK_KEY1，睡一会取拿LOCK_KEY2");
                        Thread.sleep(2000);
                        
                        synchronized (LOCK_KEY2) {
                            System.out.println(Thread.currentThread().getName() + "获取LOCK_KEY2，持有LOCK_KEY1和LOCK_KEY2");
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        
        new Thread(() -> {
            while (true) {
                try {
                    synchronized (LOCK_KEY2) {
                        System.out.println(Thread.currentThread().getName() + "获取LOCK_KEY2，睡一会取拿LOCK_KEY1");
                        Thread.sleep(2000);
                        
                        synchronized (LOCK_KEY1) {
                            System.out.println(Thread.currentThread().getName() + "获取LOCK_KEY1，持有LOCK_KEY1和LOCK_KEY2");
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        
        /**
         * 输出结果如下，程序一直无法向下推进
         * Thread-0获取LOCK_KEY1，睡一会取拿LOCK_KEY2
         * Thread-1获取LOCK_KEY2，睡一会取拿LOCK_KEY1
         */
        
        // 解决该死锁的办法有两种：令两个锁对象的获取顺序相同、另两个锁对象相同
    }
}
